package com.atguigu.gmall.activity.receiver;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.activity.mapper.SeckillGoodsMapper;
import com.atguigu.gmall.activity.util.DateUtil;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.model.activity.SeckillGoods;
import com.atguigu.gmall.model.activity.SeckillOrder;
import com.atguigu.gmall.model.activity.UserRecode;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Author WYL
 * @Date 2021/7/15 16:36
 * @Description: 商品预热
 * @Version 1.0.1
 */
@Component
public class SeckillReceiver {
    @Resource
    private SeckillGoodsMapper seckillGoodsMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 监听预热定时任务预热商品
     * @param message
     */
    @RabbitListener(queues = MqConst.QUEUE_TASK_1)
    public void importDataIntoRedis(Message message,Channel channel){
        //获取当前时间所在的时间段
        List<Date> dateMenus = DateUtil.getDateMenus();
        for (Date dateMenu : dateMenus) {
            //获取当前开始时间段
            String startTime = DateUtil.data2str(dateMenu, DateUtil.PATTERN_YYYY_MM_DDHHMM);
            //获取当前结束时间段
            Date endDate = DateUtil.addDateHour(dateMenu, 2);
            String endTime = DateUtil.data2str(endDate, DateUtil.PATTERN_YYYY_MM_DDHHMM);
            //封装查询条件
            LambdaQueryWrapper<SeckillGoods> wrapper = new LambdaQueryWrapper<>();
            //状态必须为1
            wrapper.eq(SeckillGoods::getStatus,1);
            //库存大于0
            wrapper.gt(SeckillGoods::getStockCount,0);
            //开始时间
            wrapper.eq(SeckillGoods::getStartTime,startTime);
            //结束时间
            wrapper.eq(SeckillGoods::getEndTime,endTime);
            //当前开始时间为key
            String key = DateUtil.data2str(dateMenu, DateUtil.PATTERN_YYYYMMDDHH);
            //获取已经加入缓存的商品的数据
            Set<Object> keys = stringRedisTemplate.boundHashOps(RedisConst.SECKILL_GOODS + key).keys();
            System.out.println(keys);
            if(keys != null && keys.size() > 0){
                //在Redis中没有该商品的缓存
                wrapper.notIn(SeckillGoods::getSkuId, keys);
            }
            //执行查询获取对应的结果集
            List<SeckillGoods> seckillGoodsList = seckillGoodsMapper.selectList(wrapper);
            //将活动没有结束的秒杀商品入库
            for (SeckillGoods seckillGoods : seckillGoodsList) {
                String goodsId = seckillGoods.getId();
                //将秒杀商品存入缓存
                stringRedisTemplate.boundHashOps(RedisConst.SECKILL_GOODS+key).put(goodsId, JSONObject.toJSONString(seckillGoods));
                stringRedisTemplate.boundHashOps(RedisConst.SECKILL_GOODS+key).expire(10,TimeUnit.HOURS);
//                stringRedisTemplate.boundValueOps("").set("",2, TimeUnit.HOURS);
            }
        }
    }

    /**
     * 接受消息,异步下单
     * @param message message
     * @param channel channel
     * @param msg msg
     */
    @RabbitListener(queues = MqConst.QUEUE_SECKILL_USER)
    public void importDataIntoRedis(Message message, Channel channel, String msg) {
        //将排队消息反序列化
        UserRecode userRecode = JSONObject.parseObject(msg, UserRecode.class);
        String userId = userRecode.getUserId();
        //查询用户在redis中是否有未支付的订单
        Object o = stringRedisTemplate.boundHashOps(RedisConst.SECKILL_ORDER).get(userId);
        if (o != null) {
            //设置用户的排队信息为秒杀失败,存在未支付订单
            userRecode.setStatus(4);
            stringRedisTemplate.boundValueOps(RedisConst.SECKILL_USER + userId).set(JSONObject.toJSONString(userRecode));
            return;
        }
        //若用户不存在未支付订单,则获取商品信息
        String goodsId = userRecode.getGoodsId();
        String time = userRecode.getTime();
        HashMap
        SeckillGoods seckillGoods = (SeckillGoods) stringRedisTemplate.boundHashOps(RedisConst.SECKILL_GOODS + time).get(goodsId);
        //查看商品是否卖完了
        if (seckillGoods != null) {
            //获取商品的剩余库存
            Integer stockCount = seckillGoods.getStockCount();
            //获取用户购买的数量
            Integer num = userRecode.getNum();
            //判断商品的库存是否足够
            if (stockCount >= num) {
                //生成订单
                SeckillOrder seckillOrder = new SeckillOrder();
                seckillOrder.setId(UUID.randomUUID().toString());
                seckillOrder.setCreateTime(new Date());
                seckillOrder.setGoodsId(goodsId);
                seckillOrder.setNum(num);
                seckillOrder.setMoney(num * seckillGoods.getPrice().intValue() + "");
                seckillOrder.setStatus("0");//未支付
                seckillOrder.setUserId(userId);
                //订单信息存入redis,不入库,等用户补充收货地址,支付完成后入库
                stringRedisTemplate.boundHashOps(RedisConst.SECKILL_ORDER).put(userId, seckillOrder);
                //扣减库存,计算剩余库存
                Integer stock = stockCount - num;
                if (stock > 0) {
                    //更新库存
                    seckillGoods.setStockCount(stock);
                    //重新放回redis
                    stringRedisTemplate.boundHashOps(RedisConst.SECKILL_GOODS + time).put(goodsId, seckillGoods);
                }
                //更新redis中的排队数据
                userRecode.setStatus(2);
                //设置订单的总金额
                userRecode.setMoney(Float.parseFloat(seckillOrder.getMoney()));
                //设置订单号
                userRecode.setOrderId(seckillOrder.getId());
                //更新排队信息
                stringRedisTemplate.boundValueOps(RedisConst.SECKILL_USER + userId).set(JSONObject.toJSONString(userRecode));
            }
        }
    }
    
}
